<template>
  <component :is="curEle" v-bind="curAttrs" v-on="curEvents" />
</template>

<script lang="ts">
import { isObject } from 'lodash-es'
import { getCustomComDesignInfo } from '@/store'
import { getComAttrValue } from '../../utils/attrs'
import { getInsBwUtils } from '../../utils/setupLogic'
import {
  ref,
  unref,
  markRaw,
  computed,
  watch,
  defineComponent,
  PropType,
} from 'vue'

import type { BwVueIns } from '../../utils/model'
import {
  createInsCom,
  BwVueComNameEnum,
  BwCustomComFrontTypeEnum,
  type BwCustomComStructModel,
  type BwCustomComDesignInfoModel,
  type BwGetCustomComInfoFun,
} from '@bitwit/base-com-render'

export default defineComponent({
  name: 'BwCom',
  components: {},
  props: {
    vueIns: {
      type: [Object] as PropType<BwVueIns>,
      default: undefined,
    },
    scopeData: {
      type: [Object] as PropType<Record<string, any>>,
      default: undefined,
    },
    nodeInfo: {
      type: [Object] as PropType<BwCustomComStructModel>,
      default: undefined,
    },
    forVars: {
      type: [Object] as PropType<Record<string, any>>,
      default: undefined,
    },
    frontType: {
      type: [String] as PropType<BwCustomComFrontTypeEnum>,
      default: BwCustomComFrontTypeEnum.pc,
    },
  },
  emits: [],
  setup(props) {
    const curEle = ref<any>(null)
    const renderInfo = computed(() => {
      const info = props.nodeInfo
      if (BwVueComNameEnum.component === info?.comName) {
        const vueIns = props.vueIns as BwVueIns
        const scopeData = props.scopeData as Record<string, any>
        const attrs = (info?.attrs ?? {}) as Record<string, any>

        const value = getComAttrValue(vueIns, attrs.is, scopeData)
        if (typeof value === 'string' || isObject(value)) {
          return value
        }
      }
      return null
    })

    const extendBwUtils = computed(() => {
      const utils = getInsBwUtils({ params: {} })
      return utils
    })

    const curAttrs = computed(() => {
      const info = props.nodeInfo
      const vueIns = props.vueIns as BwVueIns
      const scopeData = props.scopeData as Record<string, any>
      const attrs = (info?.attrs ?? {}) as Record<string, any>

      const value = getComAttrValue(vueIns, attrs.attrs, scopeData)

      return isObject(value) ? value : {}
    })

    const curEvents = computed(() => {
      const info = props.nodeInfo
      const vueIns = props.vueIns as BwVueIns
      const scopeData = props.scopeData as Record<string, any>
      const attrs = (info?.attrs ?? {}) as Record<string, any>

      const value = getComAttrValue(vueIns, attrs.eve, scopeData)

      return isObject(value) ? value : {}
    })

    watch(
      () => renderInfo.value,
      (newVal) => {
        if (typeof newVal === 'string') {
          curEle.value = newVal
        } else if (isObject(newVal)) {
          createInsCom(
            newVal as BwCustomComDesignInfoModel,
            props.frontType,
            getCustomComDesignInfo as BwGetCustomComInfoFun,
            unref(extendBwUtils)
          ).then((insCom: any) => {
            curEle.value = markRaw(insCom)
          })
        } else {
          curEle.value = null
        }
      },
      { deep: true, immediate: true }
    )

    return { curEle, curAttrs, curEvents }
  },
})
</script>

<style lang="less" scoped></style>
